#include "SessionModule.h"
#include "ClientAppDialogSet.h"

#include "rutil/DnsUtil.hxx"
#include "resip/dum/MasterProfile.hxx"
#include "SdpModule.h"

using namespace resip;
using namespace std;

SessionModule::SessionModule(DialogUsageManager* dum, SipStack *stack, Controller* parent) : m_sessionHandler(0), m_clientMessageHandler(0), m_serverMessageHandler(0), 
m_dialogUsageManager(dum), m_stack(stack), m_owner(parent)
{
	initialize();
}

SessionModule::~SessionModule()
{
	cleanup();
}

void SessionModule::initialize()
{
	// Initialize SessionHandler

	initializeHandler();

	// Initialize Users information

	initializeUsers();
}

void SessionModule::cleanup()
{
	if( m_sessionHandler )
	{
		delete m_sessionHandler;
		m_sessionHandler = 0;
	}
}

void SessionModule::setScheme(string scheme)
{
	m_baseAor.uri().scheme() = scheme.c_str();
	m_destAor.uri().scheme() = scheme.c_str();
}

void SessionModule::setBaseUser(string user)
{
	m_baseAor.uri().user() = user.c_str();
}

void SessionModule::setDestUser(string user)
{
	m_destAor.uri().user() = user.c_str();
}

void SessionModule::setDestHost(string uri)
{
	m_destAor.uri().host() = uri.c_str();
}

void SessionModule::setDestPassword(string password)
{
	m_password = password;
}

void SessionModule::waitForSessionResponse()
{
	FdSet fdset;
	m_stack->buildFdSet(fdset);
	fdset.selectMilliSeconds(SELECT_TIME);
	m_stack->process(fdset);

	while( m_dialogUsageManager->process() )
		;
}

void SessionModule::sendInviteMessage(string sdp)
{
	// Do necessary configuration

	m_dialogUsageManager->getMasterProfile()->setDefaultFrom(m_baseAor);
	m_dialogUsageManager->getMasterProfile()-> setDigestCredential(m_destAor.uri().host(), m_destAor.uri().user(), Data(m_password) );

	// Make INVITE message
	
	Data* txt = new Data( sdp.c_str() );

	HeaderFieldValue* hfv = new HeaderFieldValue(txt->data(), txt->size());
	Mime type("application", "sdp");
	SdpContents* sdpContents = new SdpContents(hfv, type);

	sdpContents->encode(cout);

	SharedPtr<SipMessage> request = m_dialogUsageManager->makeInviteSession(m_destAor, sdpContents, new ClientAppDialogSet(*m_dialogUsageManager));
	m_dialogUsageManager->send(request);
}

void SessionModule::sendRegularMessage(string message)
{
	// Do necessairy configuration

	m_dialogUsageManager->getMasterProfile()->setDefaultFrom(m_baseAor);
	m_dialogUsageManager->getMasterProfile()-> setDigestCredential(m_destAor.uri().host(), m_destAor.uri().user(), Data(m_password) );

	// Make REGULAR message

	ClientPagerMessageHandle handle = m_dialogUsageManager->makePagerMessage(m_destAor);
	auto_ptr<Contents> content( new PlainContents(Data(message)) );
	handle.get()->page(content);
}

void SessionModule::sendByeMessage()
{
	// Do necessairy configuration

	m_dialogUsageManager->getMasterProfile()->setDefaultFrom(m_baseAor);
	m_dialogUsageManager->getMasterProfile()-> setDigestCredential(m_destAor.uri().host(), m_destAor.uri().user(), Data(m_password) );

	// Make BYE message

	SharedPtr<SipMessage> request = m_dialogUsageManager->makeOutOfDialogRequest(m_destAor, BYE, new ClientAppDialogSet(*m_dialogUsageManager));
	m_dialogUsageManager->send(request);
}

void SessionModule::shutDown()
{
	m_sessionHandler->hangup();

	while( !m_sessionHandler->isDone() )
		;

	m_dialogUsageManager->shutdown(m_shutdownHandler);
}

void SessionModule::initializeHandler()
{
	m_sessionHandler = new SessionHandler(m_owner);
	m_dialogUsageManager->setInviteSessionHandler(m_sessionHandler);

	m_clientMessageHandler = new ClientMessageHandler(m_owner);
	m_dialogUsageManager->setClientPagerMessageHandler(m_clientMessageHandler);

	m_serverMessageHandler = new ServerMessageHandler(m_owner);
	m_dialogUsageManager->setServerPagerMessageHandler(m_serverMessageHandler);

	m_shutdownHandler = new ShutdownHandler();
}

void SessionModule::initializeUsers()
{
	m_baseAor.uri().port() = BASEPORT;
	m_baseAor.uri().host() = DnsUtil::getLocalIpAddress();

	m_destAor.uri().port() = DESTPORT;
}